/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package net.flowas.genericcrud.rest;

import static net.flowas.genericcrud.rest.CrudConstant.MODEL_TYPE;

import java.io.StringWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonWriter;
import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import net.flowas.genericcrud.RepositoryService;
import net.flowas.genericcrud.dto.PageModdel;
import net.flowas.genericcrud.dto.Pagination;
import net.flowas.genericcrud.dto.QueryOption;
import net.flowas.genericcrud.service.impl.RequestDispatcher;

/**
 * REST Web Service.
 *
 * @author Administrator
 */
//@Api(tags = "General Model Crud opration")
public class ItemsResource {
  //private RepositoryFacade viewFactory;
  private RepositoryService service;
  private RequestDispatcher dispatcher;
  private Jsonb jsonb;
  
  /*
	 * public void setViewFactory(RepositoryFacade viewFactory) { this.viewFactory =
	 * viewFactory; }
	 */

public void setService(RepositoryService service) {
	this.service = service;
}

public void setDispatcher(RequestDispatcher dispatcher) {
	this.dispatcher = dispatcher;
}

/**
   * 计数.
   * @param modelType 模型类别
   * @param option 数据
   * @return 查询结果
   */
  @POST
  @Path("{modelType}/count")
  @Produces(MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)
  public Object count(@PathParam(MODEL_TYPE) String modelType, QueryOption<Map<String,Object>> option) {	
    //return viewFactory.count(data, modelType);
	  if(option.getExample()==null) {
		  option.setExample(new HashMap<>());
	  }
	return service.count(option, dispatcher.getModelClass(modelType));
  }

  /**
   * 根据条件查询.
   * @param modelType 模型类别
   * @param option 数据
   * @return 查询结果
   */
  @POST
  @Path("{modelType}/search")
  @Produces(MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)
  public List findByCondition(@PathParam(MODEL_TYPE) String modelType, QueryOption<Map<String,Object>> option) {    
    int currentPage = 1;
    int pageSize = 10;
    Pagination pagination = option.getPagingOptions();    
    if(pagination==null) {
    	pagination =new Pagination();
    	pagination.setCurrentPage(currentPage);
    	pagination.setPageSize(pageSize);
    	option.setPagingOptions(pagination);
    }
    if(option.getExample()==null) {
    	option.setExample(new HashMap<>());
	  }
    convertParamTypes(option.getExample());
    //return viewFactory.findRang(option, modelType);
    return service.findRang(option, dispatcher.getModelClass(modelType));
  }

  
  /**
   * 根据条件查询.
   * @param modelType 模型类别
   * @param option 数据
   * @return 查询结果
   */
  @POST
  @Path("{modelType}/queryWithCount")
  @Produces(MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)
  public PageModdel queryWithCount(@PathParam(MODEL_TYPE) String modelType, QueryOption<Map<String,Object>> option) {    
    int currentPage = 1;
    int pageSize = 10;
    Pagination pagination = option.getPagingOptions();    
    if(pagination==null) {
    	pagination =new Pagination();
    	pagination.setCurrentPage(currentPage);
    	pagination.setPageSize(pageSize);
    	option.setPagingOptions(pagination);
    }
    if(option.getExample()==null) {
    	option.setExample(new HashMap<>());
	  }
    convertParamTypes(option.getExample());
    //return viewFactory.findRang(option, modelType);
    return service.queryWithCount(option, dispatcher.getModelClass(modelType));
  }
  
  @PUT
  @Path("{modelType}/update")
  @Consumes(MediaType.APPLICATION_JSON)
  public void update(@PathParam(MODEL_TYPE) String modelType, JsonObject entity) {
    //viewFactory.saveOrUpdate(modelType, entity);
	  Object entityObj = jsonToObject(modelType, entity);
	    QueryOption option = new QueryOption();
	    option.setExample(entityObj);
	service.saveOrUpdate(entityObj);
  }

  @DELETE
  @Path("{modelType}/remove/{id}")
  @Consumes(MediaType.APPLICATION_JSON)
  public void remove(@PathParam(MODEL_TYPE) String modelType, @PathParam("id") Long id) {
    //viewFactory.remove(modelType, id);
	service.remove(dispatcher.getModelClass(modelType), id);
  }

  @GET
  @Path("{modelType}/get/{id}")
  @Produces(MediaType.APPLICATION_JSON)
  public Object get(@PathParam(MODEL_TYPE) String modelType, @PathParam("id") Long id) {
    //return viewFactory.get(modelType, id);
	return service.findById(dispatcher.getModelClass(modelType), id);
  }  
  private Object jsonToObject(String modelType, JsonObject entity) {
	    StringWriter sr = new StringWriter();
	    JsonWriter jsonWriter = Json.createWriter(sr);
	    jsonWriter.writeObject(entity);
	    jsonWriter.close();
	    Object t;
	    try {
	      return getJsonb().fromJson(sr.toString(), dispatcher.getModelClass(modelType));
	    } catch (Exception e) {
	      throw new IllegalArgumentException("request parameter is not valid:",e);
	    }
	  }
  /**
   * 获取json绑定工具.
   * @return
   */
  public Jsonb getJsonb() {
    if (jsonb == null) {
      // 类实例化时创建可能导致类找不到异常，此时Osgi环境还没有处理ServiceLoader机制.
      jsonb = JsonbBuilder.create();
    }
    return jsonb;
  }
  private void convertParamTypes(Map<String, Object> conditions) {   
		if (conditions.containsKey("id")) {
	      String id = (String) conditions.get("id");
	      long idL = Long.parseLong(id.replaceAll("\"", ""));
	      conditions.put("id", idL);
	    }
	  }
}
